﻿using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Windows.Forms;

namespace UCTT.NetFx
{
    public partial class Form5 : Form
    {
        #region    字段 start
        // 矩形框坐标
        private RectangleF waferRectF = RectangleF.Empty;
        // 每次移动的偏移量
        private const float MoveOffset = 1.0F;
        // 内外环间距
        private const float RingGap = 30F;
        // 晶圆与外环的间距
        private const float WaferMargin = 100F;

        // 实线画笔
        private Pen solidPen;
        // 虚线画笔
        private Pen dashPen;

        private Font font = new Font("Microsoft YaHei UI Light", 16F, FontStyle.Bold | FontStyle.Italic);

        // 聚焦环十字准线X轴起点
        private PointF pFocusringCrossXStart = PointF.Empty;
        // 聚焦环十字准线X轴终点
        private PointF pFocusringCrossXEnd = PointF.Empty;
        // 聚焦环十字准线Y轴起点
        private PointF pFocusringCrossYStart = PointF.Empty;
        // 聚焦环十字准线Y轴终点
        private PointF pFocusringCrossYEnd = PointF.Empty;

        // 聚焦环圆心
        private PointF pFocusringOrigin = PointF.Empty;
        // 晶圆圆心
        private PointF pWaferOrigin = PointF.Empty;
        #endregion 字段 end

        #region    属性 start
        #endregion 属性 end

        #region    构造函数 start
        public Form5()
        {
            InitializeComponent();
            picb.KeyDown += new KeyEventHandler(picb_KeyDown);
            solidPen = new Pen(SystemColors.ControlDark, 2f);
            dashPen = new Pen(SystemColors.ControlDark, 2f);
            dashPen.DashStyle = DashStyle.Dash;
            dashPen.DashPattern = new float[] { 1f, 1.5f };
        }
        #endregion 构造函数 end

        #region    事件处理 start
        private void Form5_Load(object sender, EventArgs e)
        {
            this.ActiveControl = picb;

            //TestIntersectionPoint();
        }

        private void picb_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            g.SmoothingMode = SmoothingMode.HighQuality;//抗锯齿
            g.CompositingQuality = CompositingQuality.HighQuality;//合成图像的质量
            g.TextContrast = 10;
            g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;//去掉文字的锯齿

            Rectangle rect = e.ClipRectangle;
            RectangleF rectf = new RectangleF((float)rect.X - 0.7999878F, (float)rect.Y - 0.7999878F, rect.Width, rect.Height);

            rectf.Inflate(-0.8F, -0.8F);
            //rectf.Offset(-(rectf.Width / 2 + 0.7999765625F), -(rectf.Height / 2 + 0.7999765625F));
            rectf.Offset(-(rectf.Width / 2), -(rectf.Height / 2));

            g.TranslateTransform(rectf.Width / 2F, rectf.Height / 2F, MatrixOrder.Append);// 将坐标原点移动到容器中心
            GraphicsState gState = g.Save();
            g.ScaleTransform(1, -1); // 将纵坐标变换为朝上

            solidPen.Color = SystemColors.ControlDark;
            DrawFocusRing(g, rectf);
            DrawWafer(g, rectf);
            g.Restore(gState);

            g.DrawString("x-", font, SystemBrushes.ButtonShadow, pFocusringCrossXStart);
            g.DrawString("x+", font, SystemBrushes.ButtonShadow, pFocusringCrossXEnd - new SizeF(RingGap, 0));

            g.DrawString("y-", font, SystemBrushes.ButtonShadow, pFocusringCrossYStart.FlipY() - new SizeF(0, RingGap));
            g.DrawString("y+", font, SystemBrushes.ButtonShadow, pFocusringCrossYEnd.FlipY() - new SizeF(0, 5F));

            pFocusringOrigin = g.RenderingOrigin;
            g.DrawString($"({pFocusringOrigin.X},{pFocusringOrigin.Y})", font, SystemBrushes.ButtonShadow, pFocusringOrigin.X, pFocusringOrigin.Y);

            PointF pWaferOriginFlipY = pWaferOrigin.FlipY();
            g.DrawLine(dashPen, pFocusringOrigin, pWaferOriginFlipY);
            g.DrawString($"({pWaferOrigin.X},{pWaferOrigin.Y})", font, SystemBrushes.ButtonShadow, pWaferOrigin.X, pWaferOriginFlipY.Y);
        }

        private void picb_KeyDown(object sender, KeyEventArgs e)
        {
            float gap = WaferMargin - RingGap;// 晶圆与聚焦环内圆的间距
            double a = pWaferOrigin.X;
            double b = pWaferOrigin.Y;

            Debug.Print($"gap = {gap}");
            picb.Focus();
            switch (e.KeyCode)
            {
                case Keys.Up:
                    b += MoveOffset;
                    if (GetObliqueSideLength(a, b) >= gap)
                    {
                        return;
                    }
                    waferRectF.Offset(0F, MoveOffset);
                    break;
                case Keys.Down:
                    b -= MoveOffset;
                    if (GetObliqueSideLength(a, b) >= gap)
                    {
                        return;
                    }
                    waferRectF.Offset(0F, -MoveOffset);
                    break;
                case Keys.Left:
                    a -= MoveOffset;
                    if (GetObliqueSideLength(a, b) >= gap)
                    {
                        return;
                    }
                    waferRectF.Offset(-MoveOffset, 0F);
                    break;
                case Keys.Right:
                    a += MoveOffset;
                    if (GetObliqueSideLength(a, b) >= gap)
                    {
                        return;
                    }
                    waferRectF.Offset(MoveOffset, 0F);
                    break;
                default:
                    e.SuppressKeyPress = false;
                    break;
            }

            Debug.Print($"👈 = {waferRectF.Left},👆 = {waferRectF.Top},👉 = {waferRectF.Right},👇 = {waferRectF.Bottom}");
            picb.Invalidate();
        }

        private void picb_SizeChanged(object sender, EventArgs e)
        {
            if (picb.Width != picb.Height)
            {
                picb.Width = picb.Height;
            }
            picb.Invalidate();
            //picb.Left = this.Left + this.Width / 2 - picb.Width / 2;
        }

        private void Form5_FormClosed(object sender, FormClosedEventArgs e)
        {
            solidPen.Dispose();
            dashPen.Dispose();
        }
        #endregion 事件处理 end

        #region    公开方法 start

        #endregion 公开方法 end

        #region    私有方法 start
        /// <summary>
        /// 绘制聚焦环
        /// </summary>
        private void DrawFocusRing(Graphics g, RectangleF container)
        {
            RectangleF rectfOuter = container;
            // 绘制外环
            g.DrawArc(solidPen, rectfOuter, 0F, 360F);

            RectangleF rectfInner = RectangleF.Inflate(rectfOuter, -RingGap, -RingGap);
            // 绘制内环
            g.DrawArc(solidPen, rectfInner, 0F, 360F);

            // 聚焦环十字准线X轴起点
            pFocusringCrossXStart = new PointF(rectfOuter.X + RingGap, rectfOuter.Y + rectfOuter.Height / 2);
            // 聚焦环十字准线X轴终点
            pFocusringCrossXEnd = new PointF(rectfOuter.Right - RingGap, rectfOuter.Y + rectfOuter.Height / 2);

            //// 聚焦环十字准线X轴起点
            //pFocusringCrossXStart = new PointF(rectfOuter.X + RingGap, 0);
            //// 聚焦环十字准线X轴终点
            //pFocusringCrossXEnd = new PointF(rectfOuter.Right - RingGap, 0);

            // 绘制十字准线X轴
            g.DrawLine(dashPen, pFocusringCrossXStart, pFocusringCrossXEnd);

            // 聚焦环十字准线Y轴起点
            pFocusringCrossYStart = new PointF(rectfOuter.X + rectfOuter.Width / 2, rectfOuter.Y + RingGap);
            // 聚焦环十字准线Y轴终点
            pFocusringCrossYEnd = new PointF(rectfOuter.X + rectfOuter.Width / 2, rectfOuter.Bottom - RingGap);

            //// 聚焦环十字准线Y轴起点
            //pFocusringCrossYStart = new PointF(0, rectfOuter.Y + RingGap);
            //// 聚焦环十字准线Y轴终点
            //pFocusringCrossYEnd = new PointF(0, rectfOuter.Bottom - RingGap);

            // 绘制十字准线X轴
            g.DrawLine(dashPen, pFocusringCrossYStart, pFocusringCrossYEnd);

            //PointF pFocusringOrigin1 = GetIntersectionPoint(pFocusringCrossXStart, pFocusringCrossXEnd, pFocusringCrossYStart, pFocusringCrossYEnd);
        }

        /// <summary>
        /// 绘制晶圆
        /// </summary>
        private void DrawWafer(Graphics g, RectangleF container)
        {
            //float width, height = width = 300f;
            //float x = -(container.Width - width) / 2;
            //float y = -(container.Height - height) / 2;
            if (waferRectF == RectangleF.Empty)
            {
                //float retract = 100F;// 缩进距离
                waferRectF = RectangleF.Inflate(container, -WaferMargin, -WaferMargin);
                //x = waferRectF.X;
                //y = waferRectF.Y;
            }
            //width = waferRectF.Width;
            //height = waferRectF.Height;

            solidPen.Color = SystemColors.InfoText;
            // 绘制圆环
            g.DrawArc(solidPen, waferRectF, 271f, 358f);

            float x1 = waferRectF.Left + waferRectF.Width / 2 - 5;
            float y1 = waferRectF.Top - 5;
            float width1, height1 = width1 = 10f;
            // 绘制缺口圆弧
            RectangleF rectfNotch = new RectangleF(x1, y1, width1, height1);
            g.DrawArc(solidPen, rectfNotch, 0f, 180f);
            int offset = 0;// 直线两端点与矩形边框之间的间距

            solidPen.Color = Color.Purple;
            // 晶圆十字准线X轴起点
            PointF pWaferCrossXStart = new PointF(waferRectF.X + offset, waferRectF.Y + waferRectF.Height / 2);
            // 晶圆十字准线X轴终点
            PointF pWaferCrossXEnd = new PointF(waferRectF.Right - offset, waferRectF.Y + waferRectF.Height / 2);

            //// 晶圆十字准线X轴起点
            //PointF pWaferCrossXStart = new PointF(waferRectF.X + offset, 0);
            //// 晶圆十字准线X轴终点
            //PointF pWaferCrossXEnd = new PointF(waferRectF.Right - offset, 0);

            // 绘制十字准线X轴
            g.DrawLine(solidPen, pWaferCrossXStart, pWaferCrossXEnd);

            // 晶圆十字准线Y轴起点
            PointF pWaferCrossYStart = new PointF(waferRectF.X + waferRectF.Width / 2, waferRectF.Y + offset + width1 / 2);
            // 晶圆十字准线Y轴终点
            PointF pWaferCrossYEnd = new PointF(waferRectF.X + waferRectF.Width / 2, waferRectF.Bottom - offset);

            //// 晶圆十字准线Y轴起点
            //PointF pWaferCrossYStart = new PointF(0, waferRectF.Y + offset + width1 / 2);
            //// 晶圆十字准线Y轴终点
            //PointF pWaferCrossYEnd = new PointF(0, waferRectF.Bottom - offset);

            // 绘制十字准线X轴
            g.DrawLine(solidPen, pWaferCrossYStart, pWaferCrossYEnd);

            pWaferOrigin = GetIntersectionPoint(pWaferCrossXStart, pWaferCrossXEnd, pWaferCrossYStart, pWaferCrossYEnd);
        }

        /// <summary>
        /// 焦点测试
        /// </summary>
        private void TestIntersectionPoint()
        {
            // 1:无交点-两斜线长度不够交叉
            //PointF pStartA = new PointF(1, 0);
            //PointF pEndA = new PointF(4, 3);
            //PointF pStartB = new PointF(7, 3);
            //PointF pEndB = new PointF(10, 0);

            // 2:有交点-两斜线
            //PointF pStartA = new PointF(1, 0);
            //PointF pEndA = new PointF(7, 6);
            //PointF pStartB = new PointF(4, 6);
            //PointF pEndB = new PointF(10, 0);

            // 3：无交点-非重合的两平行线
            //PointF pStartA = new PointF(-2, 11);
            //PointF pEndA = new PointF(-2, -8);
            //PointF pStartB = new PointF(11, 10);
            //PointF pEndB = new PointF(11, -8);

            // 4:无交点-一直一斜长度不够交叉
            //PointF pStartA = new PointF(-2, 11);
            //PointF pEndA = new PointF(-2, -8);
            //PointF pStartB = new PointF(4, 6);
            //PointF pEndB = new PointF(10, 0);

            // 5:有交点-一直一斜
            PointF pStartA = new PointF(-2, 13);
            PointF pEndA = new PointF(-2, -8);
            PointF pStartB = new PointF(-3, 13);
            PointF pEndB = new PointF(10, 0);

            // 6：无交点-重合的两平行线
            //PointF pStartA = new PointF(-2, 11);
            //PointF pEndA = new PointF(-2, -8);
            //PointF pStartB = new PointF(-2, 13);
            //PointF pEndB = new PointF(-2, 11);

            PointF pIntersect = GetIntersectionPoint(pStartA, pEndA, pStartB, pEndB);
        }

        /// <summary>
        /// 求三角形的斜边长
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        private double GetObliqueSideLength(double a, double b)
        {
            double c = Math.Sqrt(a * a + b * b);// 两个圆心的实时偏差长度
            return c;
        }

        /// <summary>
        /// 获取两直线交点
        /// </summary>
        /// <param name="pStartA">A线段起点</param>
        /// <param name="pEndA">A线段终点</param>
        /// <param name="pStartB">B线段起点</param>
        /// <param name="pEndB">B线段终点</param>
        /// <returns></returns>
        public PointF GetIntersectionPoint(PointF pStartA, PointF pEndA, PointF pStartB, PointF pEndB)
        {
            float x1 = pStartA.X;
            float y1 = pStartA.Y;
            float x2 = pEndA.X;
            float y2 = pEndA.Y;
            float x3 = pStartB.X;
            float y3 = pStartB.Y;
            float x4 = pEndB.X;
            float y4 = pEndB.Y;
            float a = x2 == x1 ? float.PositiveInfinity : (y2 - y1) / (x2 - x1); //需考虑分母不能为0 即x2=x1 l1垂直于x轴
            float b = x4 == x3 ? float.PositiveInfinity : (y4 - y3) / (x4 - x3); //需考虑分母不能为0 即x4=x3 l2垂直于x轴

            if (a == b)
            {//斜率相同,说明平行 无交点
                Debug.WriteLine("两直线平行,无交点");
                return PointF.Empty;
            }

            float x, y = 0;

            if (x2 == x1)
            {//L1垂直于x轴  则x=x1=x2 a=infinity 想办法消除a
                x = x1;
                //(y-y3)/(x-x3)=b 且x=x1 变换得y=bx1-bx3+y3
                y = b * x1 - b * x3 + y3;
                //return new PointF(x, y);
            }
            else if (x4 == x3)
            {//L2垂直于x轴 则x=x3=x4 b=infinity 
                x = x3;
                y = a * x - a * x1 + y1;
                //return new PointF(x, y);
            }
            else
            {
                x = (a * x1 - y1 + y3 - b * x3) / (a - b);
                y = a * x - a * x1 + y1;
            }

            float XAmax = x1 > x2 ? x1 : x2;
            float XAmin = x1 < x2 ? x1 : x2;
            float YAmax = y1 > y2 ? y1 : y2;
            float YAmin = y1 < y2 ? y1 : y2;
            float XBmax = x3 > x4 ? x3 : x4;
            float XBmin = x3 < x4 ? x3 : x4;
            float YBmax = y3 > y4 ? y3 : y4;
            float YBmin = y3 < y4 ? y3 : y4;

            if (XAmax < x || x < XAmin || XBmax < x || x < XBmin || YAmax < y || y < YAmin || YBmax < y || y < YBmin)
            {
                return PointF.Empty;
            }

            //Debug.WriteLine("[{lng:'" + x1 + "',lat:'" + y1 + "'},{lng:'" + x2 + "',lat:'" + y2 + "'},{lng:'" + x3 + "',lat:'" + y3 + "'},{lng:'" + x4 + "',lat:'" + y4 + "'},{lng:'" + x + "',lat:'" + y + "'}]");
            Debug.Print($"pIntersect = X:{x},Y:{y}");
            return new PointF(x, y);
        }
        #endregion 私有方法 end
    }
}